home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mh / mh-6.8 / support / pop / popd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-14  |  9.8 KB  |  489 lines

  1. /* popd.c - the POP server */
  2. #ifndef    lint
  3. static char ident[] = "@(#)$Id: popd.c,v 1.13 1992/12/15 00:20:22 jromine Exp $";
  4. #endif    /* lint */
  5.  
  6. /* Author:    Marshall T. Rose    <MRose@UDel>    (MTR)
  7.         Department of Computer Science and Information Sciences
  8.         University of Delaware
  9.         Newark, DE  19716
  10.         302/451-1951
  11.  
  12.    Date:    Sun Oct 28 16:23:26 1984
  13.  */
  14.  
  15. #include <errno.h>
  16. #include <signal.h>
  17. #include <stdio.h>
  18. #include "../h/strings.h"
  19. #include "syslog.h"
  20. #include <sys/types.h>
  21. #include <sys/file.h>
  22. #ifndef    NOIOCTLH
  23. #include <sys/ioctl.h>
  24. #endif
  25. #include <sys/socket.h>
  26. #include <sys/time.h>
  27. #ifdef    SIGTSTP
  28. #include <sys/resource.h>
  29. #include <sys/wait.h>
  30. #endif
  31. #include <netinet/in.h>
  32. #include <netdb.h>
  33. #include <arpa/inet.h>
  34. #ifdef KPOP
  35. #include <krb.h>
  36.  
  37. static Key_schedule schedule;
  38. static KTEXT_ST ticket;
  39. static AUTH_DAT kdata;
  40. #endif
  41. #ifdef    SYS5
  42. #include <fcntl.h>
  43. #endif
  44.  
  45.  
  46. #ifdef    SYS5
  47. #define    u_short    ushort
  48. #endif
  49.  
  50. #define    NOTOK    (-1)
  51. #define    OK    0
  52.  
  53. #define    NULLCP    ((char *) 0)
  54. #define NULLRP    ((struct rusage *) 0)
  55.  
  56. #define    FAST            /* fast start-up of BBoards */
  57.  
  58. /*   */
  59.  
  60. extern int  errno;
  61. extern int  sys_nerr;
  62. extern char *sys_errlist[];
  63. extern char *sys_siglist[];
  64.  
  65.  
  66. int  debug = 0;
  67. static int  nbits = ((sizeof (int)) * 8);
  68. static int  options = 0;
  69.  
  70. #ifndef    POPSERVICE
  71. #define    POPSERVICE    "pop"
  72. #endif
  73.  
  74. char *myname = "popd";
  75. char myhost[BUFSIZ];
  76. static char *myprotocol = "tcp";
  77. static char *myservice = POPSERVICE;
  78.  
  79. static struct sockaddr_in   in_socket;
  80. static struct sockaddr_in  *isock = &in_socket;
  81.  
  82. #ifdef KPOP
  83. static AUTH_DAT kdata;
  84. #endif
  85.  
  86. static int    chldser ();
  87. void    padios (), padvise ();
  88.  
  89. static    server(), arginit(), envinit();
  90. /*   */
  91.  
  92. /* ARGSUSED */
  93.  
  94. main (argc, argv, envp)
  95. int     argc;
  96. char  **argv,
  97.       **envp;
  98. {
  99. #ifdef KPOP
  100.     int     i;
  101. #else
  102.     int     fd,
  103.             sd;
  104.     int        on = 1;
  105.     struct servent *sp;
  106.     struct sockaddr_in  out_socket,
  107.                        *osock = &out_socket;
  108. #endif
  109.  
  110. #ifdef KPOP
  111.     i = sizeof(in_socket);
  112.     if (getpeername(0, &in_socket, &i) < 0)
  113.       padios("getpeername", "bad status");
  114. #else
  115.     if ((sp = getservbyname (myservice, myprotocol)) == NULL)
  116.     padios (NULLCP, "%s/%s: unknown service", myprotocol, myservice);
  117.     isock -> sin_family = AF_INET;
  118.     isock -> sin_port = sp -> s_port;
  119.     isock -> sin_addr.s_addr = INADDR_ANY;
  120. #endif
  121.     arginit (argv);
  122.     envinit ();
  123.  
  124. #ifndef KPOP
  125. #ifdef    RESTART
  126.     for (;;) {
  127.     char    reason[BUFSIZ];
  128. #if defined(BSD42) && !defined(WAITINT)
  129.     union wait status;
  130. #else
  131.     int status;
  132. #endif
  133.  
  134.     switch (fork ()) {
  135.         case NOTOK: 
  136.         sleep (5);
  137.         continue;
  138.  
  139.         case OK: 
  140.         break;
  141.  
  142.         default: 
  143.         sleep (60);
  144.         (void) wait3 (&status, 0, NULLRP);
  145.         if (WIFEXITED (status))
  146.             (void) sprintf (reason, "exit=0%o", status.w_retcode);
  147.         else
  148.             if (WIFSIGNALED (status))
  149.             (void) sprintf (reason, "signal=%s%s",
  150.                 status.w_termsig < NSIG
  151.                 ? sys_siglist[status.w_termsig] : "unknown",
  152.                 status.w_coredump ? " (core dumped)" : NULL);
  153.             else
  154.             (void) strcpy (reason, "stopped(!!)");
  155.         padvise (NULLCP, LOG_WARNING, "%s/%s server has terminated -- %s",
  156.             sp -> s_proto, sp -> s_name, reason);
  157.         continue;
  158.     }
  159.     break;
  160.     }
  161.  
  162.     closelog ();
  163. #ifndef    BSD43
  164.     openlog (myname, LOG_PID);
  165. #else    /* BSD43 */
  166.     openlog (myname, LOG_PID, LOG_DAEMON);
  167. #endif    /* BSD43 */
  168.     padvise (NULLCP, LOG_INFO, "restart");
  169. #endif    /* RESTART */
  170.  
  171. /*   */
  172.  
  173.     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
  174.     padios ("socket", "unable to create");
  175. #ifndef    BSD43
  176.     if (options & SO_DEBUG)
  177.     if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0) == NOTOK)
  178.         padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
  179.     if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == NOTOK)
  180.     padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
  181. #else    /* BSD43 */
  182.     if (options & SO_DEBUG)
  183.     if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, &on, sizeof on) == NOTOK)
  184.         padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
  185.     if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof on) == NOTOK)
  186.     padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
  187. #endif    /* BSD43 */
  188.     if (bind (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
  189.     padios ("socket", "unable to bind");
  190.  
  191. #ifdef    SIGCHLD
  192.     (void) signal (SIGCHLD, chldser);
  193. #endif    /* SIGCHLD */
  194.     (void) listen (sd, SOMAXCONN);
  195. #endif /* KPOP */
  196. #ifdef    FAST
  197.     popinit ();
  198. #endif    /* FAST */
  199. #ifndef KPOP
  200.     for (;;) {
  201.     int     i = sizeof *osock;
  202.  
  203.     if ((fd = accept (sd, (struct sockaddr *) osock, &i)) == NOTOK) {
  204.         if (errno != EINTR)
  205.         padvise ("socket", LOG_WARNING,
  206.             "unable to accept connection on");
  207.         continue;
  208.     }
  209. #endif
  210. #ifdef    FAST
  211.     popassert ();
  212. #endif    /* FAST */
  213. #ifndef KPOP
  214.     switch (fork ()) {
  215.         case OK: 
  216.         (void) close (sd);
  217. #ifdef    SIGCHLD
  218.         (void) signal (SIGCHLD, SIG_DFL);
  219. #endif    /* SIGCHLD */
  220.         server (fd, osock);
  221.         _exit (0);
  222.  
  223.         case NOTOK: 
  224.         padvise ("socket", LOG_WARNING,
  225.             "no forks, so rejecting connection on");
  226.         default: 
  227.         (void) close (fd);
  228.     }
  229.     }
  230. #else
  231.     server (0, isock);
  232. #endif
  233. }
  234.  
  235. /*   */
  236.  
  237. static    server (fd, sin)
  238. int    fd;
  239. struct sockaddr_in *sin;
  240. {
  241.     u_short port;
  242.     struct hostent *hp;
  243.     struct in_addr *addr;
  244. #ifdef KPOP
  245.     int auth;
  246.     int sin_len;
  247.     struct sockaddr_in faddr;
  248.     char instance[INST_SZ];
  249.     char version[9];
  250.     char user[ANAME_SZ];
  251. #endif
  252.  
  253.     closelog ();
  254. #ifndef    BSD43
  255.     openlog (myname, LOG_PID);
  256. #else    /* BSD43 */
  257.     openlog (myname, LOG_PID, LOG_DAEMON);
  258. #endif    /* BSD43 */
  259.     port = ntohs (sin -> sin_port);
  260.     addr = &sin -> sin_addr;
  261.     hp = gethostbyaddr (addr, sizeof *addr, sin -> sin_family);
  262.     padvise (NULLCP, LOG_INFO, "servicing %s/%d",
  263.         hp ? hp -> h_name : inet_ntoa (*addr), port);
  264.     if (fd != 0)
  265.       {
  266.     (void) dup2 (fd, 0);
  267.     (void) close (fd);
  268.       }
  269.     (void) dup2 (0, 1);
  270.  
  271. #ifdef KPOP
  272.     sin_len = sizeof (struct sockaddr_in);
  273.     if (getpeername(0, &faddr, &sin_len) < 0) {
  274.       padvise("getpeername", LOG_INFO, "");
  275.       exit(1);
  276.     }
  277.     strcpy(instance, "*");
  278.     auth = krb_recvauth(0L, 0, &ticket, "pop", instance,
  279.             &faddr, (struct sockaddr_in *)NULL,
  280.             &kdata, "", schedule, version);
  281.     if (auth == KSUCCESS)
  282.       auth = krb_kntoln(&kdata, user);
  283.  
  284.     if (auth != KSUCCESS) {
  285.       padvise(NULLCP, LOG_INFO, "bad kerberos data, not ok'ing");
  286.       kpop (0, 1, NULLCP, NULLCP, auth); /* respond(NOTOK, krb_err_txt[auth]); */
  287.     } else {
  288.       kpop (0, 1, user, (hp ? hp -> h_name : NULLCP), 0);
  289.     }
  290. #else
  291.     pop (0, 1, sin -> sin_family == AF_INET && port < IPPORT_RESERVED && hp,
  292.         hp ? hp -> h_name : NULLCP);
  293. #endif
  294. }
  295.     
  296. /*   */
  297.  
  298. static    arginit (vec)
  299. char    **vec;
  300. {
  301.     int        port;
  302.     register char  *ap;
  303.     struct hostent *hp;
  304.  
  305.     if (myname = rindex (*vec, '/'))
  306.     myname++;
  307.     if (myname == NULL || *myname == 0)
  308.     myname = *vec;
  309.  
  310.     (void) gethostname (myhost, sizeof myhost);
  311.     if (hp = gethostbyname (myhost))
  312.     (void) strcpy (myhost, hp -> h_name);
  313. #ifndef BSD42
  314.     nbits = _NFILE;
  315. #else   /* BSD42 */
  316.     nbits = getdtablesize ();
  317. #endif  /* BSD42 */
  318.  
  319.     for (vec++; ap = *vec; vec++) {
  320.     if (*ap == '-')
  321.         switch (*++ap) {
  322.         case 'd': 
  323.             options |= SO_DEBUG;
  324.             continue;
  325.  
  326.         case 'p': 
  327.             if ((ap = *++vec) == NULL
  328.                 || *ap == '-'
  329.                 || (port = atoi (ap)) <= 0)
  330.             padios (NULLCP, "usage: %s -p portno", myname);
  331.             isock -> sin_port = htons ((u_short) port);
  332.             continue;
  333.  
  334.         default: 
  335.             padios (NULLCP, "-%s: unknown switch", ap);
  336.         }
  337.  
  338.     padios (NULLCP, "usage: %s [switches]", myname);
  339.     }
  340. }
  341.  
  342. /*   */
  343.  
  344. static  envinit () {
  345. #ifndef KPOP
  346.     int     i,
  347.             sd;
  348.  
  349.     if (!(debug = isatty (2))) {
  350.     for (i = 0; i < 5; i++) {
  351.         switch (fork ()) {
  352.         case NOTOK: 
  353.             sleep (5);
  354.             continue;
  355.  
  356.         case OK: 
  357.             break;
  358.  
  359.         default: 
  360.             _exit (0);
  361.         }
  362.         break;
  363.     }
  364.  
  365.     (void) chdir ("/");
  366.  
  367.     if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
  368.         padios ("/dev/null", "unable to read");
  369.     if (sd != 0)
  370.         (void) dup2 (sd, 0), (void) close (sd);
  371.     (void) dup2 (0, 1);
  372.     (void) dup2 (0, 2);
  373.  
  374.     if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
  375. #ifdef    TIOCNOTTY
  376.         (void) ioctl (sd, TIOCNOTTY, NULLCP);
  377. #endif    /* TIOCNOTTY */
  378.         (void) close (sd);
  379.     }
  380.     }
  381.  
  382.     for (sd = 3; sd < nbits; sd++)
  383.     (void) close (sd);
  384. #endif /* KPOP */
  385.  
  386.     (void) signal (SIGPIPE, SIG_IGN);
  387.  
  388. #ifndef    BSD43
  389.     openlog (myname, LOG_PID);
  390. #else    /* BSD43 */
  391.     openlog (myname, LOG_PID, LOG_DAEMON);
  392. #endif    /* BSD43 */
  393.     padvise (NULLCP, LOG_INFO, "starting");
  394.     if (debug)
  395.     padvise (NULLCP, LOG_DEBUG, "options=0x%x port=%d",
  396.         options, ntohs (isock -> sin_port));
  397. }
  398.  
  399. /*   */
  400.  
  401. #ifndef KPOP
  402.  
  403. /* ARGSUSED */
  404.  
  405. #ifdef    SIGCHLD
  406.  
  407. static int chldser (sig, code, sc)
  408. int    sig;
  409. long    code;
  410. struct sigcontext *sc;
  411. {
  412. #if defined(BSD42) && !defined(WAITINT)
  413.     int status;
  414. #else
  415.     union wait status;
  416. #endif
  417.  
  418.     while (wait3 (&status, WNOHANG, NULLRP) > 0)
  419.     continue;
  420. }
  421.  
  422. #endif /* SIGCHLD */
  423. #endif /* KPOP */
  424.  
  425. /*   */
  426.  
  427. /* VARARGS2 */
  428.  
  429. void    padios (what, fmt, a, b, c, d, e, f, g, h, i, j)
  430. char   *what,
  431.        *fmt,
  432.        *a,
  433.        *b,
  434.        *c,
  435.        *d,
  436.        *e,
  437.        *f,
  438.        *g,
  439.        *h,
  440.        *i,
  441.        *j;
  442. {
  443.     padvise (what, LOG_ERR, fmt, a, b, c, d, e, f, g, h, i, j);
  444.     _exit (1);
  445. }
  446.  
  447. /*   */
  448.  
  449. /* VARARGS3 */
  450.  
  451. void    padvise (what, code, fmt, a, b, c, d, e, f, g, h, i, j)
  452. char   *what,
  453.        *fmt,
  454.        *a,
  455.        *b,
  456.        *c,
  457.        *d,
  458.        *e,
  459.        *f,
  460.        *g,
  461.        *h,
  462.        *i,
  463.        *j;
  464. int    code;
  465. {
  466.     int     eindex = errno;
  467.     char    buffer[BUFSIZ];
  468.  
  469.     (void) sprintf (buffer, fmt, a, b, c, d, e, f, g, h, i, j);
  470.     if (what)
  471.     if (eindex > 0 && eindex < sys_nerr)
  472.         syslog (code, "%s %s: %s", buffer, what, sys_errlist[eindex]);
  473.     else
  474.         syslog (code, "%s %s: Error %d", buffer, what, eindex);
  475.     else
  476.     syslog (code, "%s", buffer);
  477.  
  478.     if (debug) {
  479.     fprintf (stderr, "[%d] %s", code, buffer);
  480.     if (what)
  481.         (void) fputc (' ', stderr), perror (what);
  482.     else
  483.         (void) fputc ('\n', stderr);
  484.     (void) fflush (stderr);
  485.     }
  486.  
  487.     errno = eindex;
  488. }
  489.